package com.raft.kvstore.server;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import com.alibaba.com.caucho.hessian.io.HessianOutput;
import com.raft.core.service.AddNodeCommand;
import com.raft.core.service.RemoveNodeCommand;
import com.raft.kvstore.MessageConstants;
import com.raft.kvstore.message.Failure;
import com.raft.kvstore.message.GetCommand;
import com.raft.kvstore.message.GetCommandResponse;
import com.raft.kvstore.message.Redirect;
import com.raft.kvstore.message.SetCommand;
import com.raft.kvstore.message.Success;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**按照消息类型-长度-内容
 * @author zhangsulei
 *
 */
public class Encoder extends MessageToByteEncoder<Object> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        if (msg instanceof Success) {
        	// 成功
            this.writeMessage(MessageConstants.MSG_TYPE_SUCCESS, new Success(), out);
        } else if (msg instanceof Failure) {
        	// 失败
            this.writeMessage(MessageConstants.MSG_TYPE_FAILURE, msg, out);
        } else if (msg instanceof Redirect) {
        	// 重定向
            this.writeMessage(MessageConstants.MSG_TYPE_REDIRECT, msg, out);
        } else if (msg instanceof AddNodeCommand) {
            this.writeMessage(MessageConstants.MSG_TYPE_ADD_SERVER_COMMAND, msg, out);
        } else if (msg instanceof RemoveNodeCommand) {
            this.writeMessage(MessageConstants.MSG_TYPE_REMOVE_SERVER_COMMAND, msg, out);
        } else if (msg instanceof GetCommand) {
        	// get命令
            this.writeMessage(MessageConstants.MSG_TYPE_GET_COMMAND, msg, out);
        } else if (msg instanceof GetCommandResponse) {
        	// get命令响应
            this.writeMessage(MessageConstants.MSG_TYPE_GET_COMMAND_RESPONSE, msg, out);
        } else if (msg instanceof SetCommand) {
        	// set命令
            this.writeMessage(MessageConstants.MSG_TYPE_SET_COMMAND, msg, out);
        }
    }

    /**写数据
     * @param messageType
     * @param message
     * @param out
     * @throws IOException
     */
    private void writeMessage(int messageType, Object message, ByteBuf out) throws IOException {
        out.writeInt(messageType);
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
        HessianOutput hessianOutput = new HessianOutput(byteOutput);
        // 4(messageType) + 4(bytes.length) + VAR(bytes)
        hessianOutput.writeObject(message);
        byte[] bytes = byteOutput.toByteArray();
        out.writeInt(bytes.length);
        out.writeBytes(bytes);
    }

}
